#include "GLee.h"
#include "TerrainRenderer.h"
#include "PortableGL.h"
#include <iostream>
#include <unistd.h>
using namespace glutil;

void TerrainRenderer::generateVertexBufferObjects()
{
    m_numPoints = m_model->getNumberOfPoints();
    if(m_vbufferID == 0)
    {
        glGenBuffers(1,&m_vbufferID);
        glGenBuffers(1,&m_nbufferID);
        glGenBuffers(1,&m_ibufferID);
    }
    float * verticesCoords = new float[m_numPoints*3];
    float * verticesNormals= new float[m_numPoints*3];
    for(size_t i=0;i<m_numPoints;++i)
        for(int j=0;j<3;j++)
        {
            verticesCoords[i*3+j] = m_model->getPoint(i).p.v[j];
            verticesNormals[i*3+j] = m_model->getPoint(i).n.dv[j];
        }
    glBindBuffer(GL_ARRAY_BUFFER,m_vbufferID);
    glBufferData(GL_ARRAY_BUFFER,m_numPoints*sizeof(float)*3,verticesCoords, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER,m_nbufferID);
    glBufferData(GL_ARRAY_BUFFER,m_numPoints*sizeof(float)*3,verticesNormals,GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_ibufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,m_model->getNumberOfTris()* sizeof(unsigned int)*3, &(m_model->triangles()[0]), GL_STATIC_DRAW);

    delete [] verticesCoords;
    delete [] verticesNormals;
}

void TerrainRenderer::render()
{
    if(m_vbufferID==0)
        generateVertexBufferObjects();
    glEnableClientState(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER,m_vbufferID);
    glVertexPointer(3,GL_FLOAT,0,(char*) NULL);

    int numTris = m_model->getNumberOfTris();
    glPushMatrix();
    geom::Vector3D disp = m_model->getDisplacement();
    float scale = m_model->getScale();
    glTranslatef(disp.dx,disp.dz,disp.dy);
    glScalef(scale,scale,scale);
    glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
    if(numTris > 0)
    {
        glEnable(GL_LIGHTING);
       // glEnable(GL_RESCALE_NORMAL);
        glBindBuffer(GL_ARRAY_BUFFER,m_nbufferID);
        glEnableClientState(GL_NORMAL_ARRAY);

        glNormalPointer(GL_FLOAT,0,(char*) NULL + sizeof(geom::Point3D));

        glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, m_ibufferID);
        float baseMultiplier = 0.4;
        glColor3f(m_model->baseColor()[0] *	baseMultiplier,
                  m_model->baseColor()[1] *	baseMultiplier,
                  m_model->baseColor()[2] *	baseMultiplier);

        glDrawElements(	GL_TRIANGLES, m_model->getNumberOfTris() * 3, GL_UNSIGNED_INT,NULL);

        glDisableClientState(GL_NORMAL_ARRAY);
     //   glDisable(GL_RESCALE_NORMAL);
        glEnable(GL_COLOR_MATERIAL);

    }
    else
    {
        glColor3f(1,0.3,0.3);
        glDrawArrays(GL_POINTS,0,m_model->getNumberOfPoints());

    }
    glPopMatrix();
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glDisableClientState(GL_VERTEX_ARRAY);
}

TerrainRenderer::TerrainRenderer(const geom::TerrainModel * model) : m_model(model)
{
    m_vbufferID = 0;
    m_ibufferID = 0;
    m_nbufferID = 0;
}

TerrainRenderer::~TerrainRenderer()
{
    if(m_vbufferID)
    {
        glDeleteBuffers(1,&m_vbufferID);
        glDeleteBuffers(1,&m_ibufferID);
        glDeleteBuffers(1,&m_nbufferID);
    }
}

